package com.scs.application.modules.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.flow.FlowContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.base.entity.Dept;
import com.scs.application.modules.base.entity.Matr;
import com.scs.application.modules.base.entity.MatrCategory;
import com.scs.application.modules.base.entity.Supplier;
import com.scs.application.modules.base.service.DeptService;
import com.scs.application.modules.base.service.MatrCategoryService;
import com.scs.application.modules.base.service.MatrService;
import com.scs.application.modules.base.service.SupplierService;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.finance.entity.Bill;
import com.scs.application.modules.finance.entity.BillItem;
import com.scs.application.modules.finance.entity.Settlement;
import com.scs.application.modules.finance.enums.BillStatus;
import com.scs.application.modules.finance.mapper.SettlementMapper;
import com.scs.application.modules.finance.service.BillItemService;
import com.scs.application.modules.finance.service.BillService;
import com.scs.application.modules.finance.service.SettlementService;
import com.scs.application.modules.sys.properties.ResProperties;
import com.scs.application.modules.thirdparty.dto.BillDTO;
import com.scs.application.modules.thirdparty.dto.SpBillKey;
import com.scs.application.modules.thirdparty.service.MscmService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
public class SettlementServiceImpl extends BaseServiceImpl<SettlementMapper, Settlement> implements SettlementService {

    @Autowired
    private BillService billService;

    @Autowired
    private BillItemService billItemService;

    @Autowired
    private MscmService mscmService;

    @Autowired
    private DeptService deptService;

    @Autowired
    private MatrService matrService;

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private MatrCategoryService matrCategoryService;

    @Autowired
    private ResProperties resProperties;

    /**
     * 同步帐单至供应商平台
     *
     * @param settlement
     * @return
     */
    @Override
    public void syncToMSCM(Settlement settlement) {
        List<BillDTO> spBillList = convertSpBill(settlement.getId());
        if (spBillList.size() == 0) {
            throw new BusinessException("没有任何记帐明细，不能同步");
        }

        mscmService.pushSettlements(spBillList);

        //修改结算单状态为已推送
        settlement.setFlagSyncMscm(true);
        super.updateById(settlement);

        //修改billItem状态为已推送
        List<BillItem> billItemList = billItemService.list(new QueryWrapper<BillItem>().eq("settlement_id", settlement.getId()));

        billItemList.stream().forEach(item -> item.setStatus(BillStatus.SEND.getStatus()));

        billItemService.updateBatchById(billItemList);
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        List<BillItem> billItemList = billItemService.list(new QueryWrapper<BillItem>().in("settlement_id", idList));
        if (billItemList.size() > 0) {
            billItemList.forEach(item -> item.setSettlementId("0").setStatus(BillStatus.DEFAULT.getStatus()));
            billItemService.updateBatchById(billItemList);
        }
        return this.removeByIds(idList);
    }

    @Override
    protected void beforeHandleFlowChange(FlowContext flowContext, Settlement entity) {
        //校验结算单数据字段
        String systemSettlementField = ParameterUtils.getString("system_settlement_field",null);
        if(StringUtils.isBlank(systemSettlementField)) throw new BusinessException("未设置系统参数【system_settlement_field】，请联系运营人员");
        if(!GlobalConsts.SYSTEM_SETTLEMENT_FIELDS.stream().anyMatch(s -> Objects.equals(s,systemSettlementField )))  throw new BusinessException("系统参数【system_settlement_field】参数值【"+systemSettlementField+"】非法，请联系运营人员");

        super.beforeHandleFlowChange(flowContext, entity);
        String buttonKey = flowContext.getButtonKey();
        // 提交审核，不允许空明细提交
        if ("submit".equalsIgnoreCase(buttonKey)) {
            List<BillItem> billItemList = billItemService.list(Wrappers.<BillItem>query().eq("settlement_id", flowContext.getBusId()));
            if (billItemList.size() == 0) {
                throw new BusinessException("请添加帐单明细后提交");
            }
        }
    }

    /**
     * 根据品类获取品类名称 一级-二级-三级
     * @param categoryId
     * @return
     */
    @Override
    public String getMatrCategory(String categoryId, List<MatrCategory> matrCategories) {
        if (matrCategories == null || matrCategories.size() == 0) {
            return "";
        }
        String strCategory = "";
        while (StringUtils.isNotBlank(categoryId) && !"0".equals(categoryId)) {
            final String finalCategoryId = categoryId;
            Optional<MatrCategory> optionalMatrCategory = matrCategories.stream().filter(category -> finalCategoryId.equals(category.getId())).findFirst();
            if(optionalMatrCategory.isPresent()) {
                MatrCategory matrCategory = optionalMatrCategory.get();
                categoryId = matrCategory.getParentId();
                if(StringUtils.isNotBlank(strCategory)) {
                    strCategory = matrCategory.getCategoryName() + "-" + strCategory;
                } else {
                    strCategory = matrCategory.getCategoryName();
                }

            }
        }
        return strCategory;
    }

    @Override
    public void sendMscmStock(Settlement settlement) {
        mscmService.savePeriodStock(settlement.getPeriod());
    }

    /**
     * 生成供应商推送信息
     *
     * @param settlementId
     */
    private List<BillDTO> convertSpBill(String settlementId) {

        Settlement settlement = super.getById(settlementId);
        //生成供应商记帐单String settlementId
        Map<SpBillKey, BillDTO> groupItem = Maps.newHashMap();

        List<BillItem> billItemList = billItemService.list(new QueryWrapper<BillItem>()
                .eq("settlement_id", settlement.getId()));

        final List<Supplier> suppliers = supplierService.list();

        final List<MatrCategory> matrCategories = matrCategoryService.list();
        //按供应商,消耗科室,购销类型,一物一码进行归类
        billItemList.forEach(item -> {
            //获取Bill信息
            Bill bill = billService.getById(item.getBillId());

            SpBillKey spBillKey = new SpBillKey(bill.getDeptId(), bill.getSupplierId(), bill.getFlagConsignment(), bill.getFlagOmoc());

            //创建SPBillItem
            BillDTO.BillItemDTO spBillItem = new BillDTO.BillItemDTO();

            Matr matr = matrService.getById(item.getMatrId());
            spBillItem.setMaterialId(item.getMatrId())
                    .setSpBillId(item.getBillId())
                    .setMaterialCode(matr.getMscmCode())
                    .setMaterialErpCode("")
                    .setMaterialName(item.getMatrName())
                    .setMaterialSpec(StringUtils.defaultIfBlank(item.getMatrSpec(), "默认品规"))
                    .setQty(item.getSkuQty())
                    .setUnit(item.getSkuUnit())
                    .setPrice(item.getSkuPrice())
                    .setSubtotalAmount(item.getAmount())
                    .setLot(item.getLot())
                    .setStatus(BillStatus.SETTLEMENT.getStatus())
                    .setExpDate(item.getExpDate())
                    .setMfgDate(item.getMfgDate())
                    .setManufacturerId("0")
                    .setCertificateNo(item.getCertificateNo())
                    .setHrpKey(item.getHrpKey())
                    .setSourceKey(item.getId())
                    .setCategory(getMatrCategory(matr.getCategoryId(), matrCategories))
                    .setManufacturerName(StringUtils.defaultIfBlank(item.getManufactureName(), "默认厂商"));

            if (groupItem.get(spBillKey) == null) {
                BillDTO spBill = new BillDTO();
                Supplier sp = suppliers.stream().filter(supplier -> supplier.id.equals(bill.getSupplierId())).findFirst().get();
                if (sp != null) {
                    spBill.setDeptId(bill.getDeptId())
                            .setDeptName(bill.getDeptName())
                            .setIsConsignment(bill.getFlagConsignment() ? GlobalConsts.YES_STR : GlobalConsts.NO_STR)
                            .setIsOneThingOneYard(bill.getFlagOmoc() ? GlobalConsts.YES_STR : GlobalConsts.NO_STR)
                            .setSupplierId(sp.getMscmCode())
                            .setCode(bill.getBusKey())
                            .setSupplierName(bill.getSupplierName())
                            .setItems(new ArrayList<>());
                    groupItem.put(spBillKey, spBill);
                }
            }
            groupItem.get(spBillKey).getItems().add(spBillItem);

        });
        for (SpBillKey spBillKey : groupItem.keySet()) {
            BillDTO billDTO = groupItem.get(spBillKey);
            Double totalAmount = billDTO.getItems().stream().mapToDouble(BillDTO.BillItemDTO::getSubtotalAmount).sum();

            //获取机构信息
            Dept dept = deptService.getById(billDTO.getDeptId());
            billDTO.setPeriodNo(settlement.getPeriod())
                    .setTotalAmount(totalAmount)
                    .setGmtBill(settlement.getGmtCreate())
                    .setSettlementId(settlement.getId())
                    .setDeptCode(dept == null ? "default" : dept.getOfficeSystemCode());
        }
        return groupItem.values().stream().collect(Collectors.toList());
    }


    /**
     * 导出帐单 供应商平台导入使用
     *
     * @param settlement
     * @return
     */
    @Override
    public String getDataForMSCM(Settlement settlement) {
        List<BillDTO> spBillList = convertSpBill(settlement.getId());
        if(spBillList == null || spBillList.size() == 0) throw  new BusinessException("没有可导出的数据");
        FileUtils.mkdirs(resProperties.getRealPath() + "download/settlement/");
        String fileFullName = resProperties.getRealPath() + "download/settlement/settlementBills.txt";
        FileUtils.writeTxtFile(fileFullName, JSON.toJSONString(spBillList, SerializerFeature.PrettyFormat));
        return fileFullName.substring(resProperties.getRealPath().length());
    }
}
